using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Work.API.Applications.Write.Commands;
using Work.Domain;
using Work.ErrorCode;
using Work.Infrastructure.Interfaces;

namespace Work.API.Applications.Write.CommandHandlers
{
    /// <summary>
    /// 结算支付处理器
    /// </summary>
    public class SettlePaymentCommandHandler : IRequestHandler<SettlePaymentCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<PrescriptionItem> _prescriptionItemRepo;
        private readonly IBaseRepository<Payment> _paymentRepo;
        private readonly IBaseRepository<Appintment> _appointmentRepo;

        public SettlePaymentCommandHandler(
            IBaseRepository<PrescriptionItem> prescriptionItemRepo,
            IBaseRepository<Payment> paymentRepo,
            IBaseRepository<Appintment> appointmentRepo)
        {
            _prescriptionItemRepo = prescriptionItemRepo;
            _paymentRepo = paymentRepo;
            _appointmentRepo = appointmentRepo;
        }

        public async Task<ApiResult<int>> Handle(SettlePaymentCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<int>();

            try
            {
                // 1. 验证支付金额
                if (request.PaidAmount < request.TotalAmount)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "支付金额不足";
                    result.Data = 0;
                    return result;
                }

                // 2. 获取预约信息
                var appointment = await _appointmentRepo.GetById(request.AppointmentId);
                if (appointment == null)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "预约不存在";
                    result.Data = 0;
                    return result;
                }

                // 3. 获取所有未支付的处方明细
                var prescriptionItems = await _prescriptionItemRepo.GetAll()
                    .Where(x => x.AppointmentId == request.AppointmentId 
                             && x.PaymentStatus == "未支付")
                    .ToListAsync(cancellationToken);

                if (prescriptionItems.Count == 0)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "没有需要支付的处方明细";
                    result.Data = 0;
                    return result;
                }

                // 4. 计算找零
                var change = request.PaidAmount - request.TotalAmount;

                // 5. 批量更新处方明细状态为"已支付"
                foreach (var item in prescriptionItems)
                {
                    item.PaymentStatus = "已支付";
                }
                await _prescriptionItemRepo.UpdateRange(prescriptionItems);

                // 6. 创建支付记录
                var payment = new Payment
                {
                    AppointmentId = request.AppointmentId,
                    PatientId = request.PatientId,
                    RegistrationNum = request.RegistrationNum ?? appointment.RegistrationNum,
                    TotalAmount = request.TotalAmount,
                    PaidAmount = request.PaidAmount,
                    Change = change,
                    PaymentStatus = "已支付",
                    PaymentTime = DateTime.Now,
                    PaymentMethod = request.PaymentMethod ?? "现金",
                    InvoicePrinted = request.InvoicePrinted,
                    CreateTime = DateTime.Now
                };

                var paymentRows = await _paymentRepo.AddAsync(payment);

                if (paymentRows > 0)
                {
                    result.Code = ApiEnum.成功;
                    result.Message = "结算成功";
                    result.Data = payment.PaymentId;
                }
                else
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "支付记录创建失败";
                    result.Data = 0;
                }
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.失败;
                result.Message = $"结算失败：{ex.Message}";
                result.Data = 0;
            }

            return result;
        }
    }
}

